using UnityEngine;
using System.Collections;

[AddComponentMenu( "GUI/Click Event Manager" )]
public class ClickEventManager : MonoBehaviour
{
	public bool drawDebugRays;

	private static ClickEventManager ms_rInstance;

	private bool m_bTouchScreen;
	private bool m_bInputWasPreviouslyPressed;
	private Collider m_rFirstPressedCollider;
	private Collider m_rPreviousHoveredCollider;

	void Awake( )
	{
		if( ms_rInstance == null )
		{
			ms_rInstance = this;
			//DontDestroyOnLoad( this );
		}
		else
		{
			Debug.LogWarning( "/!\\ !!! Click Manager: instance already exists !!! /!\\" );
			Destroy( this );
		}
	}

	// Use this for initialization
	void Start ()
	{
		m_rFirstPressedCollider = null;
		m_rPreviousHoveredCollider = null;
		m_bInputWasPreviouslyPressed = false;

		switch( Application.platform )
		{
			// Smartphones / tablets
			case RuntimePlatform.IPhonePlayer:
			case RuntimePlatform.Android:
			{
				m_bTouchScreen = true;
			}
			break;

			// Consoles
			case RuntimePlatform.PS3:
            //case RuntimePlatform.WiiPlayer:
			case RuntimePlatform.XBOX360:
			{
				Debug.LogWarning( "/!\\ !!! Virtual Tour Indicator: consoles are not supported !!! /!\\" );				
			}
			break;

			// Desktop PCs/Macs
			// As Unity doesn't support touch screen on these devices yet,
			// we can assume reading the mouse input only
			default:
			{
				m_bTouchScreen = false;
			}
			break;
		}

	}
	
	// Update is called once per frame
	void Update ()
	{
		Vector3 f3InputPosition = Vector3.zero;
		bool bInputIsCurrentlyPressed = false;

		// Reading input: touch screen or mouse according to the device
		
		// Touch screen
		if( m_bTouchScreen == true )
		{
			if( Input.touchCount > 0 )
			{
				Touch oFirstTouch = Input.touches[ 0 ];
				f3InputPosition.x = oFirstTouch.position.x;
				f3InputPosition.y = oFirstTouch.position.y;
	
				switch( oFirstTouch.phase )
				{
					case TouchPhase.Began:
					case TouchPhase.Moved:
					case TouchPhase.Stationary:
					{
						bInputIsCurrentlyPressed = true;
					}
					break;
				}
			}
		}
		else
		{
			// Mouse
			f3InputPosition = Input.mousePosition;
			bInputIsCurrentlyPressed = Input.GetMouseButton( 0 );			
		}

		RaycastHit oInputRaycastHitInfo;
		Ray oInputRay = Camera.mainCamera.ScreenPointToRay( f3InputPosition );
		bool bIsColliding = Physics.Raycast( oInputRay, out oInputRaycastHitInfo, Mathf.Infinity );
		Collider rCollidedElement = oInputRaycastHitInfo.collider;

		// Hovering?
		if( bIsColliding == true )
		{
			if( m_rPreviousHoveredCollider != rCollidedElement )
			{
				if( m_rPreviousHoveredCollider != null && m_rPreviousHoveredCollider != m_rFirstPressedCollider )
				{
					m_rPreviousHoveredCollider.SendMessage( "OnHoverEvent", false, SendMessageOptions.DontRequireReceiver );
				}

				if( m_rFirstPressedCollider != rCollidedElement )
				{
					rCollidedElement.SendMessage( "OnHoverEvent", true, SendMessageOptions.DontRequireReceiver );
					m_rPreviousHoveredCollider = rCollidedElement;
				}
			}
		}
		else
		{
			if( m_rPreviousHoveredCollider != null && m_rPreviousHoveredCollider != m_rFirstPressedCollider )
			{
				m_rPreviousHoveredCollider.SendMessage( "OnHoverEvent", false, SendMessageOptions.DontRequireReceiver );
				m_rPreviousHoveredCollider = null;
			}
		}

		// Input is clicking something
		if( m_bInputWasPreviouslyPressed != bInputIsCurrentlyPressed )
		{
			m_bInputWasPreviouslyPressed = bInputIsCurrentlyPressed;
			if( bIsColliding == true )
			{
				// The first collider where the user pressed is the same where the user has un-pressed
				// => it's a click!
				if( m_rFirstPressedCollider == oInputRaycastHitInfo.collider )
				{
					DrawDebugRay( oInputRay, Color.green );

					System.Diagnostics.Debug.Assert( bInputIsCurrentlyPressed == false, "/!\\ !!! Impossible case occurred !!! /!\\" );
					if( bInputIsCurrentlyPressed == false )
					{
						m_rFirstPressedCollider.SendMessage( "OnClickEvent", SendMessageOptions.DontRequireReceiver );
						m_rFirstPressedCollider = null;
					}
				}
				else if( bInputIsCurrentlyPressed == true )
				{
					// The user is starting is pressing over this collider
					m_rFirstPressedCollider = oInputRaycastHitInfo.collider;
					DrawDebugRay( oInputRay, Color.blue );
				}
				else if( m_rFirstPressedCollider != null )
				{
					// The user has pressed in the void...
					// Release the collider if any
					m_rFirstPressedCollider.SendMessage( "OnHoverEvent", false, SendMessageOptions.DontRequireReceiver );
					m_rFirstPressedCollider = null;
					DrawDebugRay( oInputRay, Color.blue );
				}
			}
			else
			{
				if( bInputIsCurrentlyPressed == false && m_rFirstPressedCollider != null )
				{
					m_rFirstPressedCollider.SendMessage( "OnHoverEvent", false, SendMessageOptions.DontRequireReceiver );
					m_rFirstPressedCollider = null;
				}

				DrawDebugRay( oInputRay, Color.red );
			}
		}
	}

	private void DrawDebugRay( Ray a_oRayToDraw, Color a_oRayColor )
	{
		if( drawDebugRays == true )
		{
			Debug.DrawRay( a_oRayToDraw.origin, a_oRayToDraw.direction, a_oRayColor, 5.0f );
		}
	}
}
